#include <Uefi.h>
#include <Library/UefiLib.h>

EFI_STATUS
EFIAPI
UefiMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
    EFI_STATUS Status;
    EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutputProtocol;

    Status = SystemTable->BootServices->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&GraphicsOutputProtocol);

    if (EFI_ERROR(Status))
    {
      Print(L"CapsuleApp: NO GOP is found.\n");
      return EFI_UNSUPPORTED;
    }

    if (GraphicsOutputProtocol->Mode->MaxMode - 1 != GraphicsOutputProtocol->Mode->Mode)
    {
      // GraphicsOutputProtocol->SetMode(GraphicsOutputProtocol, GraphicsOutputProtocol->Mode->MaxMode - 1);
    }

    for (UINT32 i = 0; i < GraphicsOutputProtocol->Mode->MaxMode; i++)
    {
      UINTN SizeOfInfo;
      EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
      Status = GraphicsOutputProtocol->QueryMode(GraphicsOutputProtocol, i, &SizeOfInfo, &Info);
      Print(L"Mode %d: %d x %d\n", i, Info->HorizontalResolution, Info->VerticalResolution);
      Print(L"Version: %d\n", Info->Version);
      Print(L"SizeOfInfo: %d\n", SizeOfInfo);
      Print(L"PixelFormat: %d\n", Info->PixelFormat);
      Print(L"PixelInformation: 0x%X\n", Info->PixelInformation);
      Print(L"PixelsPerScanLine: %d\n", Info->PixelsPerScanLine);
      Print(L"\n");
    }

    Print(L"MaxMode: %d\n", GraphicsOutputProtocol->Mode->MaxMode);
    Print(L"Current Mode %d: %d x %d\n", GraphicsOutputProtocol->Mode->Mode, GraphicsOutputProtocol->Mode->Info->HorizontalResolution, GraphicsOutputProtocol->Mode->Info->VerticalResolution);
    Print(L"Version: %d\n", GraphicsOutputProtocol->Mode->Info->Version);
    Print(L"SizeOfInfo: %d\n", GraphicsOutputProtocol->Mode->SizeOfInfo);
    Print(L"PixelFormat: %d\n", GraphicsOutputProtocol->Mode->Info->PixelFormat);
    Print(L"PixelInformation: 0x%X\n", GraphicsOutputProtocol->Mode->Info->PixelInformation);
    Print(L"PixelsPerScanLine: %d\n", GraphicsOutputProtocol->Mode->Info->PixelsPerScanLine);
    Print(L"FrameBufferBase: 0x%X\n", GraphicsOutputProtocol->Mode->FrameBufferBase);
    Print(L"FrameBufferSize: %d\n", GraphicsOutputProtocol->Mode->FrameBufferSize);

    EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION FillColor;

    FillColor.Raw = 0x000000FF; // Blue/Red
    GraphicsOutputProtocol->Blt(
        GraphicsOutputProtocol,
        &FillColor.Pixel,
        EfiBltVideoFill,
        0, 0,
        0, 0,
        GraphicsOutputProtocol->Mode->Info->HorizontalResolution,
        GraphicsOutputProtocol->Mode->Info->VerticalResolution,
        0
    );

    FillColor.Raw = 0x0000FF00; // Green
    GraphicsOutputProtocol->Blt(
        GraphicsOutputProtocol,
        &FillColor.Pixel,
        EfiBltVideoFill,
        0, 0,
        0, 0,
        GraphicsOutputProtocol->Mode->Info->HorizontalResolution,
        GraphicsOutputProtocol->Mode->Info->VerticalResolution,
        0
    );

    FillColor.Raw = 0x00FF0000; // Red/Blue
    GraphicsOutputProtocol->Blt(
        GraphicsOutputProtocol,
        &FillColor.Pixel,
        EfiBltVideoFill,
        0, 0,
        0, 0,
        GraphicsOutputProtocol->Mode->Info->HorizontalResolution,
        GraphicsOutputProtocol->Mode->Info->VerticalResolution,
        0
    );

    return EFI_SUCCESS;
}